#include "../crypto/ecdsa/ecs_locl.h"
#include "../crypto/ecdh/ech_locl.h"

#include "pecc.h"

int (*old_ecdsa_do_verify)(const unsigned char *dgst, int dgst_len, 
			const ECDSA_SIG *sig, EC_KEY *eckey);

#ifndef OPENSSL_NO_ECDSA
/* Our internal ECDSA_METHOD that we provide pointers to */
#if 1 /* REMOVE THIS */ 
static ECDSA_METHOD pecc_ecdsa = 
	{
	"ECC OPENMPTEST ECDSA method", /* const char *name; */
	NULL, /* ECDSA_SIG *(*ecdsa_do_sign)(const unsigned char *dgst, int dgst_len, 
			const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey); */
	NULL, /* int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, 
			BIGNUM **r); */
	sleep1_test, /* int (*ecdsa_do_verify)(const unsigned char *dgst, int dgst_len, 
			const ECDSA_SIG *sig, EC_KEY *eckey); */
/*
#if 0
	int (*init)(EC_KEY *eckey);
	int (*finish)(EC_KEY *eckey);
#endif
*/
	0, /* int flags; */
	NULL /* char *app_data; */
	};
#endif /* REMOVE THIS */
#endif

#ifndef OPENSSL_NO_ECDH
/* Our internal DH_METHOD that we provide pointers to */
#if 0 /* REMOVE THIS */
static ECDH_METHOD pecc_ecdh =
	{
	"PECC OPENMPTEST ECDH method", /* const char *name; */
	NULL, /* int (*compute_key)(void *key, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh,
	                   void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen)); */
/*
#if 0
	int (*init)(EC_KEY *eckey);
	int (*finish)(EC_KEY *eckey);
#endif
*/
	0, /* int flags; */
	NULL /* char *app_data; */
	};
#endif /* REMOVE THIS */
#endif

/* Constants used when creating the ENGINE */
static const char *engine_e_pecc_id = "pecc-openmptest";
static const char *engine_e_pecc_name = "PECC-OPENMPTEST engine support";

/* This internal function is used by ENGINE_pecc() and possibly by the
 * "dynamic" ENGINE support too */
static int e_pecc_bind_helper(ENGINE *e)
	{
#if 0
#ifndef OPENSSL_NO_RSA
	const RSA_METHOD *meth1;
#endif
#endif
#ifndef OPENSSL_NO_ECDSA
/*REMOVE THIS*/	const ECDSA_METHOD *meth2;
#endif
#ifndef OPENSSL_NO_ECDH
/*REMOVE THIS*///	const ECDH_METHOD *meth3;
#endif
	if(!ENGINE_set_id(e, engine_e_pecc_id) ||
			!ENGINE_set_name(e, engine_e_pecc_name) ||
#if 0
#ifndef OPENSSL_NO_RSA
			!ENGINE_set_RSA(e, &e_pecc_rsa) ||
#endif
#endif
#ifndef OPENSSL_NO_ECDSA
/*REMOVE THIS*/	!ENGINE_set_ECDSA(e, &pecc_ecdsa) ||
#endif
#ifndef OPENSSL_NO_ECDH
/*REMOVE THIS*///	!ENGINE_set_ECDH(e, &pecc_ecdh) ||
#endif
			!ENGINE_set_destroy_function(e, e_pecc_destroy) ||
			!ENGINE_set_init_function(e, e_pecc_init) ||
			!ENGINE_set_finish_function(e, e_pecc_finish) ||
			!ENGINE_set_ctrl_function(e, e_pecc_ctrl) ||
			!ENGINE_set_cmd_defns(e, e_pecc_cmd_defns))
		return 0;

#if 0
#ifndef OPENSSL_NO_RSA
	meth1 = RSA_PKCS1_SSLeay();
	e_pecc_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
	e_pecc_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
	e_pecc_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
	e_pecc_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
	e_pecc_rsa.bn_mod_exp = meth1->bn_mod_exp;
#endif
#endif

#ifndef OPENSSL_NO_ECDSA
	/* Use the DSA_OpenSSL() method and just hook the mod_exp-ish
	 * bits. */
	meth2 = ECDSA_OpenSSL();
	pecc_ecdsa.ecdsa_do_sign = meth2->ecdsa_do_sign;
	pecc_ecdsa.ecdsa_sign_setup = meth2->ecdsa_sign_setup;
	old_ecdsa_do_verify = meth2->ecdsa_do_verify;//pecc_ecdsa.ecdsa_do_verify = meth2->dsa_do_verify;
#endif

#ifndef OPENSSL_NO_DH
	/* Much the same for Diffie-Hellman */
	//meth3 = ECDH_OpenSSL();
	//atalla_dh.generate_key = meth3->generate_key;
	//atalla_dh.compute_key = meth3->compute_key;
#endif

	/* Ensure the e_pecc error handling is set up */
	ERR_load_PECC_strings();
	return 1;
	}
	
#if 0
/* HACK - use text I/O functions in openssl and PECC to handle conversions. This
 * is vile. */
static int bn2pecc(const BIGNUM *bn, mpz_t g)
	{
	int toret;
	char *tmpchar = BN_bn2hex(bn);
	if(!tmpchar) return 0;
	toret = (mpz_set_str(g, tmpchar, 16) == 0 ? 1 : 0);
	OPENSSL_free(tmpchar);
	return toret;
	}

static int pecc2bn(mpz_t g, BIGNUM *bn)
	{
	int toret;
	char *tmpchar = OPENSSL_malloc(mpz_sizeinbase(g, 16) + 10);
	if(!tmpchar) return 0;
	mpz_get_str(tmpchar, 16, g);
	toret = BN_hex2bn(&bn, tmpchar);
	OPENSSL_free(tmpchar);
	return toret;
	}
#endif

